﻿// This source code file contains modifications authored by Microsoft Corporation. 
// All such modifications are copyright (c) Microsoft Corporation. All rights reserved.

namespace ODataValidator.RuleEngine
{
    #region Namespaces
    using System.Collections.Generic;
    using System.Linq;

    #endregion

    /// <summary>
    /// Facade class to simplify accesses to Interop validation rule engine
    /// </summary>
    public class RuleEngineWrapper
    {
        /// <summary>
        /// The interop context for theis facade wrapper to work at.
        /// </summary>
        private ServiceContext context;

        /// <summary>
        /// The result provider to consume the validation results.
        /// </summary>
        private IResultProvider resultConsumer;

        /// <summary>
        /// The logger to log runtime failures.
        /// </summary>
        private ILogger logger;

        /// <summary>
        /// List of categories of all applicable rules to be validate against.
        /// </summary>
        private List<string> categories;

        /// <summary>
        /// List of rules applicable to the interop context
        /// </summary>
        private List<Rule> rules = new List<Rule>();

        /// <summary>
        /// Create a facade view of interop validation engine for the current context 
        /// </summary>
        /// <param name="context">the current request context object</param>
        /// <param name="resultProvider">consumer of validation results generated by interop rule engine</param>
        /// <param name="logger">logger object</param>
        /// <param name="ruleList">Pre-set rule list</param>
        public RuleEngineWrapper(ServiceContext context, IResultProvider resultProvider, ILogger logger, List<string> ruleList = null)
        {
            this.context = context;
            this.resultConsumer = resultProvider;
            this.logger = logger;
            this.rules = this.context.GetRules().ToList();
            if (null != ruleList && ruleList.Count > 0)
            {
                this.rules = (from r in this.rules where ruleList.Contains(r.Name) select r).ToList();
            }
            this.categories = (from r in this.rules select r.Category).Distinct().ToList();
        }

        /// <summary>
        /// Get applicable categories for a specific Interop session
        /// </summary>
        /// <param name="context">context of the Interop session</param>
        /// <returns></returns>
        public IEnumerable<string> Categories  
        { 
            get 
            { 
                return this.categories; 
            } 
        }

        /// <summary>
        /// Property to return the number of rules applicable to the service context
        /// </summary>
        public int RuleCount
        {
            get
            {
                return this.rules.Count;
            }
        }

        /// <summary>
        /// Validate applicable rules and produce results to the registered result consumer
        /// </summary>
        public void Validate()
        {
            (new RuleExecuter(this.resultConsumer, this.logger)).Execute(this.context, this.rules.ToArray());
        }
    }
}
